﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace Halfwit
{
    /// <summary>
    /// Attached property to facilitate autocomplete on usernames in TextBoxes
    /// </summary>
    public class UsernameLookup
    {
        public static UsernameLookupTrigger GetTrigger(DependencyObject obj)
        {
            return (UsernameLookupTrigger)obj.GetValue(TriggerProperty);
        }

        public static void SetTrigger(DependencyObject obj, UsernameLookupTrigger value)
        {
            obj.SetValue(TriggerProperty, value);
        }

        private static void OnKeyUp(object sender, KeyEventArgs e)
        {
            var updateText = sender as TextBox;
            if (updateText == null) return;

            // if control or alt is down, forget it
            if (Keyboard.Modifiers != ModifierKeys.None && Keyboard.Modifiers != ModifierKeys.Shift) return;

            // if shift is down it has to be for _ or capital letters
            if (Keyboard.Modifiers == ModifierKeys.Shift && e.Key != Key.Subtract && (e.Key < Key.A || e.Key > Key.Z)) return;

            if ((e.Key < Key.D0 || e.Key > Key.D9) &&
                (e.Key < Key.A || e.Key > Key.Z) &&
                (e.Key != Key.Subtract || Keyboard.Modifiers != ModifierKeys.Shift)) return;

            var searchText = updateText.Text.Substring(0, updateText.CaretIndex);

            int startPos = 0;
            if (GetTrigger(updateText) == UsernameLookupTrigger.AtSign)
            {
                startPos = searchText.LastIndexOf('@');
                if (startPos < 0) return;

                startPos++;
            }

            searchText = searchText.Substring(startPos, searchText.Length - startPos);
            if (searchText.Length == 0) return;

            var anyInvalidChars = searchText.Any(c => c != '_' && !Char.IsLetterOrDigit(c));
            if (anyInvalidChars) return;

            var firstMatchingName = TwitterConnection.RecentUserNames
                .Where(n => n.StartsWith(searchText, StringComparison.OrdinalIgnoreCase))
                .OrderBy(n => n)
                .FirstOrDefault();
            if (firstMatchingName == null) return;

            e.Handled = true;
            updateText.SelectedText = firstMatchingName.Substring(searchText.Length);
        }

        private static void ue_Unloaded(object sender, RoutedEventArgs e)
        {
            var ue = sender as TextBox;
            if (ue == null) return;

            ue.Unloaded -= ue_Unloaded;
            ue.KeyUp -= OnKeyUp;
        }

        public static readonly DependencyProperty TriggerProperty =
            DependencyProperty.RegisterAttached("Trigger", typeof(UsernameLookupTrigger), typeof(UsernameLookup), new UIPropertyMetadata(UsernameLookupTrigger.None, TriggerChanged));

        static void TriggerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var ue = d as TextBox;
            if (ue == null) return;

            var v = (UsernameLookupTrigger)e.NewValue;
            if (v != UsernameLookupTrigger.None)
            {
                ue.Unloaded += ue_Unloaded;
                ue.KeyUp += OnKeyUp;
            }
            else
            {
                ue.KeyUp -= OnKeyUp;
            }
        }
    }

    public enum UsernameLookupTrigger
    {
        None,
        AtSign,
        StartOfText
    }
}
